#include <console.hpp>
#include <logger.hpp>
#include <settings.hpp>

// 命令行最大长度
#define CMD_LEN		 (1024)
// 历史记录最多条数
#define HISTORY_SIZE (1000)

#define HISTORY_NAME "history"

#define HISTORY_PATH "/flash/history.txt"

#define CMDLINE_NAME "QS:> "

const char* rcS = "rcS";
const char* rcT = "rcT";

static Console* s_Console = nullptr;

static std::map<const char*, void*, ptr_cmp_s> m_MainFuncs;

// [由Python生成
extern void py_console_resister_main(void);
// 由Python生成]

// 注册模块主函数
int ConsoleRegister(const char* cmd, void* entry)
{
	if (cmd == nullptr)
	{
		return -1;
	}
	if (entry == nullptr)
	{
		return -1;
	}
	m_MainFuncs[cmd] = entry;
	return 0;
}

Console* Console::Instance(void)
{
	if (s_Console == nullptr)
	{
		s_Console = new Console();
	}
	return s_Console;
}

Console::Console()
	: TaskRun()
	, m_NeedSave(false)
{
	// 由Python生成的
	py_console_resister_main();
	// 载入历史命令
	LoadHistory();
}

Console::~Console()
{
}

void Console::Start(void* arg)
{
	TaskRun::Start(arg);
	m_HisSave.Start(this);
}

void Console::Run(void* arg)
{
	// 从rcs执行启动默认模块
	ExecFromRcs();
	usleep(100 * 1000);
	while (1)
	{
		// 读取用户输入
		char* line = readline(CMDLINE_NAME);
		// 去首尾空格
		std::string cmd = StringTrimed(std::string(line));
		// 如果命令不为空
		if (cmd.size() > 0)
		{
			// 加入到历史列表
			AddHistory(cmd);
			// 执行命令行
			ExecCmdLine(cmd);
		}
		// 释放内存
		free(line);
	}
	// 从历史列表中清除所有命令
	clear_history();
	// 从rcT执行停止默认模块
	ExecFromRct();
}

std::vector<char*> Console::SplitCommandLine(const std::string& cmdLine)
{
	std::vector<char*> args;
	std::istringstream iss(cmdLine);
	std::string token;

	// 参数由空格分隔
	while (std::getline(iss, token, ' '))
	{
		if (!token.empty())
		{											// 忽略空参数
			char* arg = new char[token.size() + 1]; // 分配内存
			std::strcpy(arg, token.c_str());		// 复制参数内容
			args.push_back(arg);					// 将指针添加到向量中
		}
	}

	return args;
}

// 执行命令行
int Console::ExecCmdLine(std::string line)
{
	std::vector<char*> args = SplitCommandLine(line);
	// 执行模块主函数
	int ret = Exec(args);
	// 更新保存标记
	m_NeedSave = true;
	// 释放参数列表内存
	for (char* arg : args)
	{
		delete[] arg;
	}
	// 返回模块执行结果
	return ret;
}

// 载入历史命令
int Console::LoadHistory(void)
{
	char* path = GetPrgFilePath(HISTORY_NAME);
	std::ifstream infile(path);
	free(path);

	if (!infile)
	{
		return -1;
	}

	std::string line;
	while (std::getline(infile, line))
	{
		m_HisCmds.push_back(line);
	}
	infile.close();

	while (m_HisCmds.size() > HISTORY_SIZE)
	{
		std::string cmd = m_HisCmds.front();
		m_HisCmds.pop_front();
	}

	for (std::string elem : m_HisCmds)
	{
		add_history(elem.c_str());
	}

	return 0;
}

// 保存历史命令
int Console::SaveHistory(void)
{
	if (!m_NeedSave)
	{
		return -1;
	}

	char* path = GetPrgFilePath(HISTORY_NAME);
	std::ofstream outfile(path);
	free(path);

	if (!outfile)
	{
		return -1;
	}

	for (std::string elem : m_HisCmds)
	{
		outfile << elem << std::endl;
	}

	outfile.close();
	m_NeedSave = false;

	return 0;
}

// 加入历史命令
int Console::AddHistory(std::string line)
{
	add_history(line.c_str());

	m_HisCmds.push_back(line);

	while (m_HisCmds.size() > HISTORY_SIZE)
	{
		m_HisCmds.pop_front();
	}
	return 0;
}

// 显示历史命令
int Console::ShowHistory(void)
{
	int i = 0;
	for (std::string elem : m_HisCmds)
	{
		LOGI("%04d: %s\n", i++, elem.c_str());
	}
	return 0;
}

// 从rcS载入自动启动列表
int Console::ExecFromRcs(void)
{
	char* path = GetPrgFilePath(rcS);
	std::ifstream infile(path);
	free(path);

	if (!infile)
	{
		return -1;
	}

	std::string line;
	while (std::getline(infile, line))
	{
		std::string cmd = StringTrimed(line);
		// 如果不是空行且没有被注释掉
		if (cmd.size() > 0 && cmd[0] != '#')
		{
			// 执行命令行
			ExecCmdLine(cmd);
		}
	}
	infile.close();
	return 0;
}

// 从rcT载入自动停止列表
int Console::ExecFromRct(void)
{
	char* path = GetPrgFilePath(rcT);
	std::ifstream infile(path);
	free(path);

	if (!infile)
	{
		return -1;
	}

	std::string line;
	while (std::getline(infile, line))
	{
		std::string cmd = StringTrimed(line);
		// 如果不是空行且没有被注释掉
		if (cmd.size() > 0 && cmd[0] != '#')
		{
			// 执行命令行
			ExecCmdLine(cmd);
		}
	}
	infile.close();
	return 0;
}

// 执行模块主函数
int Console::Exec(std::vector<char*> args)
{
	// 得到参数个数
	int argc = args.size();
	if (argc <= 0)
	{
		LOGE("cmd error.\n");
		return -1;
	}

	// 分配char**数组和nullptr终止符的空间
	char** argv = new char*[argc + 1];
	// 复制指针到char**数组
	for (int i = 0; i < argc; ++i)
	{
		argv[i] = args[i];
	}

	if (strcmp(args[0], "exit") == 0)
	{
		SaveHistory();
		exit(0);
		return 0;
	}

	if (strcmp(args[0], "history") == 0)
	{
		ShowHistory();
		return 0;
	}

	// 从树中获取模块名的入口函数
	int (*cmd_entry)(int, char**) = (int (*)(int, char**))m_MainFuncs[argv[0]];
	if (cmd_entry == nullptr)
	{
		LOGE("cmd not found.\n");
		return -1;
	}

	// 执行模块主函数
	int ret = cmd_entry(argc, argv);
	// 释放内存
	delete[] argv;
	return ret;
}

ConsoleAutoSaveHistory::ConsoleAutoSaveHistory()
	: TaskRun()
{
}

ConsoleAutoSaveHistory::~ConsoleAutoSaveHistory()
{
}

void ConsoleAutoSaveHistory::Run(void* arg)
{
	if (arg == nullptr)
	{
		return;
	}
	Console* pConsole = (Console*)arg;

	while (1)
	{
		uint32_t ms = g_Settings->history_cmd_save_ms;
		if (ms == 0)
		{
			ms = 15000;
		}
		pConsole->SaveHistory();
		usleep(ms * 1000);
	}
}

/// Test example commands

/* @RegistMainFunction */
int eg1_main(int argc, char** argv)
{
	LOGI("cmd \"eg1\"\n");
	for (int i = 0; i < argc; i++)
	{
		LOGI("\t\"%s\"\n", argv[i]);
	}

	return 0;
}

/* @RegistMainFunction */
int eg2_main(int argc, char** argv)
{
	char buff[200];
	int len = 0;
	for (int i = 0; i < argc; i++)
	{
		len += snprintf(buff + len, 200, "%s ", argv[i]);
	}
	len += snprintf(buff + len, 200, "\n");
	LOGI(buff);

	return 0;
}
